﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using EnvSafe.Expression;

namespace Heroius.Abacus
{
    internal partial class FormCal : Form
    {
        int RecordPointer = 20;
        string[] Records = new string[21];

        internal FormCal()
        {
            InitializeComponent();
            for (int i = 0; i < Records.Length; i++)
            {
                Records[i] = "";
            }
            ListOp.Items.AddRange(Program.OpFac.GetAvailableOperatorNames());

            WriteLine("叨叨小算盘 - by Heroius", Color.OrangeRed);
            System.Version va = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
            WriteOperation(string.Format("版本:{0}.{1}", va.Major, va.Minor), Color.BlueViolet);
        }

        private void FormCal_Load(object sender, EventArgs e)
        {
            tbIn.Focus();
        }

        #region 常规按键响应
        //将按键上显示的内容插入到当前位置，不适用于单目函数
        private void keyboard_Click(object sender, EventArgs e)
        {
            Button CurrentBtn = sender as Button;
            string i = CurrentBtn.Text;
            int p = tbIn.SelectionStart;
            tbIn.SelectedText = i;
            tbIn.Focus();
            tbIn.SelectionStart = p + i.Length;
        }
        //算符的插入
        private void ListOp_DoubleClick(object sender, EventArgs e)
        {
            if (ListOp.SelectedIndex != -1)
            {
                string Op = ListOp.SelectedItem.ToString();
                int p = tbIn.SelectionStart;
                tbIn.SelectedText = Op + "()";
                tbIn.Focus();
                tbIn.SelectionStart = p + Op.Length + 1;
            }
        }
        //计算确定键
        private void Go_Click(object sender, EventArgs e)
        {
            int p = tbIn.SelectionStart;
            int l = tbIn.SelectionLength;
            try
            {
                nextpage();
                WriteLine("Input:");
                WriteOperation(tbIn.Text);
                WriteLine("Output:");
                Records[RecordPointer] = Program.Maker.GenerateProcedure(tbIn.Text).Calculate();
                lbOut.Text = Records[RecordPointer];
            }
            catch (ExpressionException eex)
            {
                lbOut.Text = eex.Message;
            }
            catch
            {
                lbOut.Text = "The Expression Just Input Is Illegal, Please Check It.";
            }
            finally
            {
                WriteOperation(lbOut.Text, Color.Blue);
                tbIn.Focus();
                tbIn.SelectionStart = p;
                tbIn.SelectionLength = l;
            }
        }
        //清除输入框
        private void btnC_Click(object sender, EventArgs e)
        {
            tbIn.Clear();
            tbIn.Focus();
            tbIn.SelectionStart = 0;
        }
        //清除光标前字符
        private void Back_Click(object sender, EventArgs e)
        {
            int p = tbIn.SelectionStart - 1;
            if (p == -1)
            {
                p++;
            }
            else
            {
                if (tbIn.SelectedText == "")
                    tbIn.Select(p, 1);
            }
            tbIn.SelectedText = "";
            tbIn.Focus();
            tbIn.SelectionStart = p;
        }
        #endregion

        #region 菜单响应
        private void 复制结果ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //复制结果内容到剪贴板
            Clipboard.SetDataObject(lbOut.Text);
        }

        private void 粘贴数值ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //从剪贴板粘贴内容到输入框
            IDataObject CuData = Clipboard.GetDataObject();
            if (CuData.GetDataPresent(DataFormats.Text))
            {
                int p = tbIn.SelectionStart;
                string i = CuData.GetData(DataFormats.Text).ToString();
                int l = i.Length;
                tbIn.SelectedText = i;
                tbIn.Focus();
                tbIn.SelectionStart = p + l;
            }
        }

        private void 说明文档ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //todo:打开说明文件
            try { System.Diagnostics.Process.Start(Application.StartupPath + "/Abacus.chm"); }
            catch { MessageBox.Show(this, "未找到帮助文件。"); }
        }

        private void 关于AToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new AboutBox().ShowDialog();
        }

        #endregion

        #region 拖放
        private void memory_DragEnter(object sender, DragEventArgs e)
        {
            Label CurrentLabel = sender as Label;
            if (e.Data.GetDataPresent(DataFormats.Text))
                e.Effect = DragDropEffects.Copy;
        }

        private void memory_MouseDown(object sender, MouseEventArgs e)
        {
            Label CurLb = sender as Label;
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                CurLb.DoDragDrop(CurLb.Text, DragDropEffects.Copy);
            }
        }

        private void memory_DragDrop(object sender, DragEventArgs e)
        {
            Label CurLb = sender as Label;
            string teller = e.Data.GetData(DataFormats.Text).ToString();
            try { Convert.ToDouble(teller); }
            catch { return; }
            CurLb.Text = teller;
        }

        private void Input_DragDrop(object sender, DragEventArgs e)
        {
            TextBox CurTb = sender as TextBox;
            string teller = e.Data.GetData(DataFormats.Text).ToString();
            try { Convert.ToDouble(teller); }
            catch { return; }
            CurTb.SelectedText = teller;
        }

        private void Input_DragEnter(object sender, DragEventArgs e)
        {
            TextBox CurTb = sender as TextBox;
            if (e.Data.GetDataPresent(DataFormats.Text))
                e.Effect = DragDropEffects.Copy;
        }
        #endregion

        #region 记录控制

        void prepage()
        {
            if (RecordPointer == 0)
                RecordPointer = 20;
            else
                RecordPointer--;
            lbRn.Text = (RecordPointer + 1).ToString();
            lbOut.Text = Records[RecordPointer].ToString();
        }

        void nextpage()
        {
            if (RecordPointer == 20)
                RecordPointer = 0;
            else
                RecordPointer++;
            lbRn.Text = (RecordPointer + 1).ToString();
            lbOut.Text = Records[RecordPointer].ToString();
        }

        private void btnLeft_Click(object sender, EventArgs e)
        {
            prepage();
        }

        private void btnRight_Click(object sender, EventArgs e)
        {
            nextpage();
        }

        private void toFirst_Click(object sender, EventArgs e)
        {
            RecordPointer = 20;
            nextpage();
        }

        private void toLast_Click(object sender, EventArgs e)
        {
            RecordPointer = 0;
            prepage();
        }

        private void GiveTo_Click(object sender, EventArgs e)
        {
            int p = tbIn.SelectionStart;
            int l = tbIn.SelectionLength;
            try
            {
                Convert.ToDouble(lbOut.Text);
                tbIn.SelectedText = lbOut.Text;
                p += lbOut.Text.Length;
                l = 0;
            }
            catch { return; }
            finally
            {
                tbIn.Focus();
                tbIn.SelectionStart = p;
                tbIn.SelectionLength = l;
            }
        }

        private void GetFrom_Click(object sender, EventArgs e)
        {
            int p = tbIn.SelectionStart;
            int l = tbIn.SelectionLength;
            try
            {
                nextpage();
                Records[RecordPointer] = tbIn.SelectedText;
                lbOut.Text = Records[RecordPointer];
            }
            catch
            {
                lbOut.Text = "Only a Number Can Be Given to a Record.";
            }
            finally
            {
                tbIn.Focus();
                tbIn.SelectionStart = p;
                tbIn.SelectionLength = l;
            }
        }
        #endregion

        #region Window Movement

        bool Moving
        {
            get { return _moving; }
            set
            {
                _moving = value;
                OriginLocation = MousePosition;
            }
        }
        bool _moving = false;

        Point OriginLocation;

        private void PnlHead_MouseMove(object sender, MouseEventArgs e)
        {
            if (Moving)
            {
                var srcp = PointToScreen(e.Location);
                int LocX = this.Location.X + srcp.X - OriginLocation.X;
                int LocY = this.Location.Y + srcp.Y - OriginLocation.Y;
                OriginLocation = srcp;
                this.Location = new Point(LocX, LocY);
            }
        }

        private void PnlHead_MouseDown(object sender, MouseEventArgs e)
        {
            Moving = true;
        }

        private void PnlHead_MouseUp(object sender, MouseEventArgs e)
        {
            Moving = false;
        }

        private void PnlHead_MouseLeave(object sender, EventArgs e)
        {
            Moving = false;
        }

        #endregion

        #region Record Window

        internal void WriteLine(string Content)
        {
            Console.AppendText(string.Format("{0}\n", Content));
        }

        internal void WriteLine(string Content, Color ForeColor)
        { Console.SelectionColor = ForeColor; Console.AppendText(string.Format("{0}\n", Content)); Console.SelectionColor = Color.Black; }

        internal void WriteOperation(string Content, Color ForeColor)
        {
            Console.SelectionAlignment = HorizontalAlignment.Right;
            Console.SelectionColor = ForeColor;
            WriteLine(Content);
            Console.SelectionColor = Color.Black;
            Console.SelectionAlignment = HorizontalAlignment.Left;
        }

        internal void WriteOperation(string Content) { WriteOperation(Content, Color.Green); }

        private void MiCopy_Click(object sender, EventArgs e)
        {
            if (Console.SelectedText != string.Empty)
            {
                Clipboard.SetText(Console.SelectedText);
            }
            else
            {
                MessageBox.Show("没有选中的文本。");
            }
        }

        private void MiExport_Click(object sender, EventArgs e)
        {
            DiaExport.ShowDialog();
        }

        private void DiaExport_FileOk(object sender, CancelEventArgs e)
        {
            Console.SaveFile(DiaExport.FileName);
        }

        private void MiClear_Click(object sender, EventArgs e)
        {
            Console.Clear();
            WriteLine("叨叨小算盘 - by Heroius", Color.OrangeRed);
            System.Version va = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
            WriteOperation(string.Format("版本:{0}.{1}", va.Major, va.Minor), Color.BlueViolet);
        }

        #endregion

        private void BtnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ListOp_SelectedIndexChanged(object sender, EventArgs e)
        {
            TipOP.RemoveAll();
            if (ListOp.SelectedIndex == -1)
            {
                TipOP.SetToolTip(ListOp, "未选中任何算符");
            }
            else
            {
                string name = ListOp.SelectedItem.ToString();
                TipOP.SetToolTip(ListOp, string.Format("当前选中的算符:{0}\n\n{1}", name, OpInfo.ResourceManager.GetString(name)));
            }
        }
    }
}